package com.jasonzqshen.ifm.collections.treeCollection.factories;

import java.util.Hashtable;

import org.w3c.dom.Element;

import com.jasonzqshen.ifm.collections.treeCollection.*;

/**
 * Can only contain one tree root
 * 
 * @author Jason
 * 
 */
public abstract class TreeFactory {
    private String treeClassName;

    private TreeRootFactory rootFactory;

    private Hashtable<String, TreeObjectFactory> factoryTable;

    /**
     * Tree Class Name
     * 
     * @param treeType
     */
    public TreeFactory(String treeClassName) {
        factoryTable = new Hashtable<String, TreeObjectFactory>();
        this.treeClassName = treeClassName;
    }

    /**
     * get Class Type
     * 
     * @return
     */
    public final String getTreeClassName() {
        return this.treeClassName;
    }

    /**
     * Register factory
     * 
     * @param factory
     */
    public final void addTreeObjectFactory(TreeObjectFactory factory)
            throws TreeFactoryException {
        if (factory instanceof TreeRootFactory) {
            if (rootFactory != null) {
                throw new TreeFactoryException(
                        "TreeRoot factory already exists");
            }
            rootFactory = (TreeRootFactory) factory;
        }

        this.factoryTable.put(factory.getTreeClassName(), factory);
    }

    /**
     * Get Object Register based on class name
     * 
     * @param index
     * @return
     */
    public final TreeObjectFactory getObjectFactory(String index) {
        return factoryTable.get(index);
    }

    /**
     * Get all Tree object types
     * 
     * @return
     */
    public final String[] getAllTypes() {
        return (String[]) this.factoryTable.keySet().toArray();
    }

    /**
     * Get all tree object registers
     * 
     * @return
     */
    public final TreeObjectFactory[] getAllRegisters() {
        return (TreeObjectFactory[]) this.factoryTable.values().toArray();
    }

    /**
     * 
     * @return
     */
    public final TreeRootFactory getTreeRootFactory() {
        return rootFactory;
    }

    /**
     * Construct Tree
     * 
     * @param args
     * @return
     */
    public abstract Tree ConstructTree(Object[] args);

    /**
     * Construct Tree With Tree Root
     * 
     * @param args
     * @return
     */
    public abstract Tree ConstructTreeWithRoot(TreeRoot root, Object[] args);

    /**
     * public delegate void TreeXmlParse(XElement xelem, Tree tree);
     */
    public abstract void xmlParser(Element elem, Tree Tree);
}
